﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Xml.Linq;
using COFE.Core.Utils;
using System.Runtime.Serialization;
using COFE.Core;

namespace COFE.Web
{
    /// <summary>
    /// Represents a link in entry or search, a link enable access a property of it or perform an action.    
    /// </summary>
    public class Link : ISupportXml
    {
        #region Constructor

        /// <summary>
        /// Constructor using MediaType, RelationType and Uri
        /// </summary>
        /// <param name="type"></param>
        /// <param name="rel"></param>
        /// <param name="uri"></param>
        public Link(MediaType type, RelationType rel, string uri)
        {
            MediaType = type;
            Relation = rel;
            Uri = uri;
        }

        /// <summary>
        /// Constructor using MediaType, relation type string (for COFE Metadata) and Uri.
        /// </summary>
        /// <param name="type"></param>
        /// <param name="rel"></param>
        /// <param name="uri"></param>
        public Link(MediaType type, string rel, string uri)
        {
            MediaType = type;
            RelationString = rel;

            Uri = uri;
        }

        #endregion

        #region Methods

        public override bool Equals(object obj)
        {
            if (obj is Link)
            {
                Link objLink = obj as Link;
                return MediaType == objLink.MediaType &&
                    Relation == objLink.Relation &&
                    Uri == objLink.Uri;
            }
            return false;
        }

        public override int GetHashCode()
        {
            return Uri.GetHashCode();
        }


        /// <summary>
        /// Serialize the link object to xml.
        /// </summary>
        /// <returns></returns>
        public XElement ToXml(bool indentLinks = false)
        {
            return new XElement(XNames.Link,
                                 new XAttribute(XNames.MediaType, MediaType.ToMIME()),
                                 new XAttribute(XNames.RelationType, RelationString),
                                 new XAttribute(XNames.Uri, Uri));
        }

        /// <summary>
        /// Deserialize stream to link object.
        /// </summary>
        /// <param name="itemXml"></param>
        /// <returns></returns>
        public static Link FromXml(XElement itemXml)
        {
            MediaType mType = MediaTypeExtension.Parse(itemXml.Attribute(XNames.MediaType).Value);
            RelationType rType = RelationTypeExtension.Parse(itemXml.Attribute(XNames.RelationType).Value);                            
            string uri = itemXml.Attribute(XNames.Uri).Value;

            if (rType == RelationType.Unknown)
                return new Link(mType, itemXml.Attribute(XNames.RelationType).Value, uri);

                return new Link(mType, rType, uri);
        }

        #endregion

        #region Data

        private string _relationString = null;

        #endregion

        #region Public Properties

        /// <summary>
        /// Gets the type of what the link returns.
        /// </summary>
        public MediaType MediaType { get; set; }

        /// <summary>
        /// Gets the relation to hosting type (e.g. entry or search).
        /// </summary>
        public RelationType Relation { get; set; }

        /// <summary>
        /// Gets or sets relation string to hosting type (e.g. entry or search), you can set either Relation or RelationString.
        /// </summary>
        public string RelationString
        {
            get
            {
                if (Relation == RelationType.Property && _relationString != null)
                    return _relationString;
                else
                    return Relation.ToString();
            }
            set
            {
                _relationString = value;
                Relation = RelationType.Property;
            }

        }

        /// <summary>
        /// Gets the link target.
        /// </summary>
        public string Uri { get; set; }

        #endregion
    }
}